package com.cheejee.goodscenter.validated;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.cheejee.goodscenter.service.exception.CheckException;

import cn.hutool.core.collection.CollectionUtil;

/**
 * 参数校验切面，对所有标记了@Check的方法参数进行参数校验。
 * 
 * @author CARRY
 * @Date 2020年10月22日上午11:52:38
 */
@Aspect
@Component
public class ValidatedAspect {

	@Resource
	private Validator validator;

	/**
	 * 进行参数校验，如果是List类型会对list的每个对象进行校验
	 *
	 * @param joinPoint
	 * @param check
	 * @throws CheckException
	 */
	@Before("@annotation(check)")
	public void doValidated(JoinPoint joinPoint, Check check) throws CheckException {

		Object[] args = joinPoint.getArgs();
		String[] message = check.message();
		String signature = joinPoint.getSignature().toString();
		MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
		String[] prams = methodSignature.getParameterNames();

		for (int i = 0; i < args.length; i++) {

			if (args[i] == null) {
				throw new CheckException(message[i], prams[i], null, signature);
			}

			if (args[i] instanceof List) {
				List<Object> list = new ArrayList<>((List<Object>) args[i]);
				list.removeAll(Collections.singleton(null));
				
				if(!check.IgnoreEmptyList() && CollectionUtil.isEmpty(list)) {
					throw new CheckException(message[i], prams[i], null, signature);
				}
				
				for(Object o : list) {
					if(o == null) {
						continue;
					}
					check(o, prams[i], check.group(), signature);
				}
				
			} else {
				check(args[i], prams[i], check.group(), signature);
			}

		}
	}
	

	private void check(Object arg, String pram, Class<?>[] group, String signature) {
		Set<ConstraintViolation<Object>> constraintViolations = validator.validate(arg, group);
		if (!constraintViolations.isEmpty()) {
			throw new CheckException(constraintViolations.iterator().next().getMessage(), pram, arg.toString(), signature);
		}
	}
}
